a9a068
@@ -155,6 +155,10 @@
public abstract class TransactionSynchronizationManager {
 		// Transparently remove ResourceHolder that was marked as void...
 		if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
 			map.remove(actualKey);
+			// Remove entire ThreadLocal if empty...
+			if (map.isEmpty()) {
+				resources.remove();
+			}
 			value = null;
 		}
 		return value;
@@ -176,8 +180,13 @@
public abstract class TransactionSynchronizationManager {
 			map = new HashMap<Object, Object>();
 			resources.set(map);
 		}
-		if (map.put(actualKey, value) != null) {
-			throw new IllegalStateException("Already value [" + map.get(actualKey) + "] for key [" +
+		Object oldValue = map.put(actualKey, value);
+		// Transparently suppress a ResourceHolder that was marked as void...
+		if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) {
+			oldValue = null;
+		}
+		if (oldValue != null) {
+			throw new IllegalStateException("Already value [" + oldValue + "] for key [" +
 					actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
 		}
 		if (logger.isTraceEnabled()) {
@@ -226,6 +235,10 @@
public abstract class TransactionSynchronizationManager {
 		if (map.isEmpty()) {
 			resources.remove();
 		}
+		// Transparently suppress a ResourceHolder that was marked as void...
+		if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
+			value = null;
+		}
 		if (value != null && logger.isTraceEnabled()) {
 			logger.trace("Removed value [" + value + "] for key [" + actualKey + "] from thread [" +
 					Thread.currentThread().getName() + "]");
